//
//  Font.swift
//  amb_iOS
//
//  Created by HFY on 2022/7/20.
//

import UIKit

/// 字体组件
///
/// 只需要对接 Font.Map 与配置文件就可以实现字体更换
/// 全局配置，请赋值 给 Font.Map 中 share 属性即可
///
/// 如何全局替换UIFont？
///
/// 只需要全局搜索 UIFont.systemFont 和 UIFont.boldSystemFont 去掉前面 UI 2个字符全局替换即可
/// 其他UIFont替换可再自定义
open class Fonts {
    
    /// 字体映射model
    ///
    /// 对接设计师时，就应该说明支持的字体样式只有model中这几种
    /// 假如 字体文件名是 xxx.otf
    /// json文件应该如下：
    /// ```json
    /// {"thin": "xxx.otf", "light": "xxx.otf", ...}
    /// ```
    ///
    /// 或者xml如下
    /// ```xml
    /// <xml>
    /// <thin>xxx.otf</tin>
    /// <light>xxx.otf</light>
    /// </xml>
    ///```
    ///
    /// Weight 根据配置文件
    /// 至少有一个全局的 配置文件
    /// 如果 单独view 有单独的配置文件
    /// 那就有单独的一个 weight
    public class Map {
        
        var thin: String?
        var light: String?
        var regular: String?
        var medium: String?
        var semibold: String?
        var bold: String?
        var heavy: String?
        var black: String?
        
        /// 全局的 weight
        public static var share: Map?
        
        fileprivate lazy var mirror: Mirror = {
            
            return Mirror(reflecting: self)
        }()
        
        fileprivate func fontName(of style: Weight) ->String? {
            
            let styleStr = style.rawValue
            let child = self.mirror.children.filter { $0.label == styleStr }.first
            return child?.value as? String
        }
        
    }
    
    /// 对应的 UIFont.weight 中的静态函数
    ///
    /// 兼顾UIFont 的调用方式
    public enum Weight: String {
        
        case thin = "thin"
        
        case light = "light"
        
        case regular = "regular"
        
        case medium = "medium"
        
        case semibold = "semibold"
        
        case bold = "bold"
        
        case heavy = "heavy"
        
        case black = "black"
        
        
        var UIFontWeight: UIFont.Weight {
            
            switch self {
            case .thin:
                return UIFont.Weight.thin
            case .light:
                return UIFont.Weight.light
            case .regular:
                return UIFont.Weight.regular
            case .medium:
                return UIFont.Weight.medium
            case .semibold:
                return UIFont.Weight.semibold
            case .bold:
                return UIFont.Weight.bold
            case .heavy:
                return UIFont.Weight.heavy
            case .black:
                return UIFont.Weight.black
            }
            
        }
        
    }
    
    public static func systemFont(ofSize: CGFloat, weight: Weight? = nil, map: Map? = Map.share) ->UIFont {
        
        guard let weight = weight else {
            return UIFont.systemFont(ofSize: ofSize)
        }
        
        guard let map = map, let fontName = map.fontName(of: weight) else {
            return UIFont.systemFont(ofSize: ofSize, weight: weight.UIFontWeight)
        }
        return UIFont(name: fontName, size: ofSize) ?? Fonts.systemFont(ofSize: ofSize)
        
    }
    
    public static func boldSystemFont(ofSize: CGFloat, map: Map? = Map.share) ->UIFont {
        
        let weight = Weight.bold
        guard let map = map, let fontName = map.fontName(of: weight) else {
            return UIFont.boldSystemFont(ofSize: ofSize)
        }
        return UIFont(name: fontName, size: ofSize) ?? Fonts.systemFont(ofSize: ofSize)
    }
    
    
}
